from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

from myapp.models import User,Goods,Cate,Comment,UserFlow
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

#导入序列化对象
from myapp.myser import UserSer,GoodsSer,CateSer,CommentSer

# mongoDB
from pymongo import MongoClient
from bson import json_util as jsonb

import math


# 建立mongo连接
cli = MongoClient(host='127.0.0.1',port=27017)
db = cli.md
table = db.tags

#定义地址和端口
host = '127.0.0.1'
port = 6379

#建立redis连接
r = redis.Redis(host=host,port=port)


# 获取n名数据
def get_top_n(num):

    # 获取redis排行榜
    goods_click = r.zrange('good_rank',0,-1,desc=True,withscores=True)[:num]

    goods = Goods.objects.in_bulk([int(item[0]) for item in goods_click])
    print(goods)
    res = []
    for item in goods_click:
        try:
            res.append({int(item[1]):goods[int(item[0])]})
        except Exception as e:
            pass
    return res


# 商品检索
class GoodsSearch(APIView):
    
    def get(self,request):
        
        work = request.GET.get('work',None)
        goodslist = Goods.objects.filter(Q(name__icontains=work)|Q(desc__icontains=work))

        ser = GoodsSer(goodslist,many=True)

        return Response(ser.data)


# 商品排行榜返回
class GoodsRank(APIView):

    def get(self,request):

        get_res = get_top_n(10)
        res = []

        for item in get_res:
            for k,v in item.items():
                # 序列化
                data = GoodsSer(v).data
                # 将商品点击数附加到数据中
                data['clicks'] = k
                res.append(data)

        return Response(res)


# 商品点击
class GoodsClick(APIView):

    def get(self,request):
        # 接收参数
        gid = request.GET.get('gid',None)

        # 修改商品点击数
        r.zincrby("good_rank",1,int(gid))

        return Response({"message":"访问了"})



# 美化方法
def dictfetchall(cursor):

	#获取游标描述
	desc = cursor.description

	return [dict(zip( [col[0] for col in desc ] ,row)) 
        for row in cursor.fetchall()
        ]

def userisflow(request):
    gid = request.GET.get('gid',None)
    uid = request.GET.get('uid',None)

    cursor = connection.cursor()
    cursor.execute('select a.id from goods a left join userflow b on a.id = b.gid where b.uid = %s' % str(uid))

    res = dictfetchall(cursor)
    print(res)
    for i in res:
        if str(i["id"]) == str(gid):
            return JsonResponse({'code':200})
    return JsonResponse({'code':403})

    
    


# 关注（取关）接口
class GetFlow(APIView):

    def get(self,request):

        gid = request.GET.get('gid',None)
        uid = request.GET.get('uid',None)
        type = request.GET.get('type',1)   #1 关注

        # 关注
        if int(type) == 1:
            
            userflow = UserFlow(gid=int(gid),uid=int(uid))
            code = 200
            message = '关注成功'
            goods = Goods.objects.filter(id=int(gid)).first()
            try:
                userflow.save()
            except Exception as e:
                code = 403
                message = '已经关注过一次了'
            goods.flow +=  1
            goods.save()
            
            
        # 取关
        elif int(type) == 2:
            
            flow = UserFlow.objects.filter(gid=int(gid),uid=int(uid))
            if flow:
                
                flow.delete()
                goods = Goods.objects.filter(id=int(gid)).first()
                goods.flow -=  1
                goods.save()
                message = '取关成功'
                code = 200
            else:
                message = '错误请求'
                code = 403
        else:
            gids = request.GET.get('gids',None)
            if gids == []:
                message = '请选择您需要取关的商品'
                code = 403
            else:
                gids = eval(gids)
                for i in gids:
                    UserFlow.objects.filter(gid=int(i),uid=int(uid)).delete()
                message = '批量取关'
                code = 200

            
        
        return Response({'message':message,'code':code})


# 商品关注接口(商品被哪些用户关注)
class GidFlow(View):

    def get(self,request):
        gid = request.GET.get('gid',None)

        # 建立游标对象
        cursor = connection.cursor()

        cursor.execute('select a.username from user a left join userflow b on a.id = b.uid where b.gid = %s'%str(gid))

        res = dictfetchall(cursor)

        return HttpResponse(json.dumps(res,ensure_ascii=False,indent=4,default=str),content_type='application/json')

# 商品关注接口(用户关注的商品列表)
class UidFlow(View):

    def get(self,request):
        uid = request.GET.get('uid',None)

        # 建立游标对象
        cursor = connection.cursor()
        # 执行sql语句
        cursor.execute('select a.name,a.id from goods a left join userflow b on a.id = b.gid where b.uid = %s' % str(uid))

        # 获取结果集
        # res = cursor.fetchall()
        res = dictfetchall(cursor)

        return HttpResponse(json.dumps(res,ensure_ascii=False),content_type='application/json')




# 展示评论
class CommentList(APIView):

    def get(self,request):
        # 商品id、
        gid = request.GET.get('gid')
        page = int(request.GET.get('page'))
        show_page = 3

        start_index = (page-1) * show_page  #开始索引
        end_index = page * show_page   #结束索引    


        # 查询评论
        comment = Comment.objects.filter(gid=int(gid)).order_by("-id")[start_index:end_index]

        # 评论的页码列表
        count = Comment.objects.filter(gid=int(gid)).count()
        p = math.ceil(count / show_page)
        pages = [i for i in range(1,int(p)+1)]
        # 上一页 下一页
        prev_page = page - 1
        next_page = page + 1
        # if prev_page < 1:
        #     prev_page = 1
        # if next_page > pages[-1]:
        #     next_page = pages[-1]

        print(CommentSer(Comment.objects.filter(gid=int(gid)).order_by("-id"),many=True).data)


         # 序列化
        comment_str = CommentSer(comment,many=True)

        res = {}   #最终的 容器
        res['data'] = comment_str.data
        res['pages'] = pages
        res['prev_page'] = prev_page
        res['next_page'] = next_page
        res['last'] = p


        return Response(res)



# 添加评论
class InsertComment(APIView):

    def post(self,request):
        # 初始化参数
        comment = CommentSer(data=request.data) 
        uid = request.POST.get('uid')

        if r.get(str(uid)):
            return Response({'code':403})

        # 数据校验
        if comment.is_valid():
            comment.save()
            r.set(str(uid),'123')
            r.expire(str(uid),10)
        
        
        return Response({'code':200})


# 在线人数
class GetOnLine(APIView):

    def get(self,request):

        if 'HTTP_X_FORWARDED_FOR' in request.META:
            ip =  request.META['HTTP_X_FORWARDED_FOR']
        else:
            ip = request.META['REMOTE_ADDR']
        
        r.sadd('online',ip)
        r.expire('online',20)

        myset = r.smembers('online')
        return Response({'online':len(myset)})

# 展示标签
class GetTags(View):

    def get(self,request):
        id = request.GET.get('id',None)
        res = table.find_one({"gid":str(id)})
        print(res)

        # redis 获取标签
        # l = r.llen(str(id))
        # rs = r.lrange(str(id),0,l+1)
        # print([i.decode('utf-8') for i in rs])

        return HttpResponse(jsonb.dumps(res,ensure_ascii=False))


# 添加标签接口
class InsertTags(APIView):

    def get(self,request):
        id = request.GET.get('id',None)
        tags = request.GET.get('tags',None)

        tags = tags.split(",")
        
        # 排重
        res = table.find({'gid':str(id)}).count()

        if res > 0:
            return Response({'message':'重复数据'})
        # mango 储存标签
        table.insert({'gid':str(id),'tags':tags})
        # redis 存储
        # for item in tags:
        #     r.lpush(str(id),item)

        return Response({'message':'添加成功'})
    def put(self,request):
        id = request.GET.get('id',None)
        tags = request.GET.get('tags',None)

        tags = tags.split(",")
        # 查询
        res = table.find_one({"gid":str(id)})
        
        if res:
            # mango 修改标签
            table.update({'gid':str(id)},{'$set':{'tags':tags}})
        else:
            table.insert({'gid':str(id),'tags':tags})

        return Response({})



# 商品详情
class GoodsShow(APIView):

    def get(self,request):
        gid = request.GET.get('gid',None)

        goods = Goods.objects.filter(id=gid).first()

        ser = GoodsSer(goods).data
        cate = Cate.objects.filter(id=goods.cate_id).first()
        res = {}
        res['data'] = ser
        res['cate'] = cate.name

        return Response(res)

# 商品列表页
class GoodsList(APIView):

    def get(self,request):
        # 当前页
        page = int(request.GET.get('page',1))
        # 一页多少商品
        size = int(request.GET.get('size',1))
        #从哪开始切
        data_start = (page - 1) * size
        # 切到哪
        data_end = page * size

        #查询数据
        goodslist = Goods.objects.all()[data_start:data_end]

        # 查询总数量
        count = Goods.objects.count()

        data = GoodsSer(goodslist,many=True).data
        # 总页数
        p = count / size
        index = str(p).find('.')
        if str(p)[index+1:] != '0':
            p += 1
            p = str(p)[:index]
        #  页数列表
        pages = [i for i in range(1,int(p)+1)]
        res = {}
        res['total'] = count
        res['data'] = data
        res['pages'] = pages
        # 上一页
        prev = page - 1
        #下一页
        next = page + 1
        if prev == 0:
            prev = 1
        if next == pages[-1]+1:
            next  = pages[-1]
        res['prev'] = prev
        res['next'] = next

        return Response(res)


# 添加商品
class InsertGoods(APIView):

    def post(self,request):
        name = request.data.get('name')
        desc = request.data.get('desc')
        cate_id = request.data.get('cate_id')
        price = request.data.get('cate_id')
        params = request.data.get('params')

        goods = Goods.objects.filter(name=name).first()

        if goods:
            res = {}
            res['code'] = 405
            res['message'] = '商品已存在'
            return Response(res)

        g = Goods(name=name,desc=desc,cate_id=cate_id,params=params,price=price)
        g.save()
        goo = Goods.objects.filter(name=name).first()
        r.set(str(goo.id),str(goo.params))
        res = {}
        res['code'] = 200
        res['message'] = '保存成功'
        res['id'] = goo.id
        return Response(res)
    
    def put(self,request):
        id = request.data.get('id')
        name = request.data.get('name')
        desc = request.data.get('desc')
        cate_id = request.data.get('cate_id')
        price = request.data.get('cate_id')
        params = request.data.get('params')
        print(desc)
        # 修改
        goods = Goods.objects.filter(id=id).first()
        goods.name = name
        goods.desc = desc
        goods.cate_id = cate_id
        goods.price = price
        goods.params = params
        goods.save()

        return Response({'message':'修改成功'})


class CateView(APIView):

    def get(self,request):
        cid = request.GET.get('cid',None)
        
        if cid:
            cate = Cate.objects.filter(id=cid).first()
            res = {}
            res['cate'] = cate.name
            return Response(res)

        cate = Cate.objects.all()

        ser = CateSer(cate,many=True)

        return Response(ser.data)

